package com.google.android.apps.iosched.gcm;

import android.content.Context;

import com.google.android.apps.iosched.Config;
import com.google.android.gcm.GCMRegistrar;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import static com.google.android.apps.iosched.util.LogUtils.LOGD;
import static com.google.android.apps.iosched.util.LogUtils.LOGE;
import static com.google.android.apps.iosched.util.LogUtils.LOGI;
import static com.google.android.apps.iosched.util.LogUtils.LOGV;
import static com.google.android.apps.iosched.util.LogUtils.makeLogTag;
/**
 * Created by Alex on 13-12-3.
 */
public class ServerUtilities {

    private static final String TAG = makeLogTag("GCM");

    private static final int MAX_ATTEMPTS = 5;
    private static final int BACKOFF_MILLIS = 2000;

    private static final Random sRandom =  new Random();

    /**
     * 注册,发送成功返回true，发送失败返回false
     * @param context
     * @param regId
     * @return
     */
    public static boolean register(final Context context,final String regId){

        LOGI(TAG,"registering device (regId="+regId+")");
        String serverUrl = Config.GCM_SERVER_URL + "/register";
        Map<String,String> params = new HashMap<String,String>();
        params.put("regId",regId);

        long backoff = BACKOFF_MILLIS + sRandom.nextInt(1000);

        for (int i = 1; i<= MAX_ATTEMPTS; i++){
            LOGV(TAG,"Attempt #" + i + "to register");
            try {
                post(serverUrl, params);
                GCMRegistrar.setRegisteredOnServer(context,true);
                return true;
            }catch (IOException e){
                LOGE(TAG,"Failed to register on attempt "+i ,e);
                if(i == MAX_ATTEMPTS){
                    break;
                }

                try {
                    LOGV(TAG,"Sleeping for "+ backoff+"ms before retry");
                    Thread.sleep(backoff);
                }catch (InterruptedException ie){
                    LOGD(TAG,"Thread interrupted : abort remaining retries!");
                    Thread.currentThread().interrupt();
                    return false;
                }

                backoff *= 2;

            }
        }

        return false;
    }

    /**
     * 取消注册
     * @param context
     * @param regId
     */
    static void unregister(final Context context,final String regId){
        LOGI(TAG,"unregistering device (regId = " + regId+")" );
        String serverUrl = Config.GCM_SERVER_URL + "/unregister";
        Map<String,String> params = new HashMap<String, String>();
        params.put("regId",regId);
        try {
            post(serverUrl,params);
            GCMRegistrar.setRegisteredOnServer(context,false);
        } catch (IOException e){
            LOGD(TAG," Unable to unregister from application server",e);
        }
    }


    /**
     * 进行post发送内容
     * @param endpoint
     * @param params
     */
    private static void post(String endpoint,Map<String,String> params) throws IOException{
        URL url;
        try {
            url = new URL(endpoint);
        }catch (MalformedURLException e){
            throw new IllegalArgumentException("invalid url:"+endpoint);
        }

        StringBuilder bodyBuilder = new StringBuilder();
        Iterator<Entry<String,String>> iterator = params.entrySet().iterator();

        while(iterator.hasNext()){
            Entry<String,String> param = iterator.next();
            bodyBuilder.append(param.getKey()).append('=').append(param.getValue());
            if (iterator.hasNext()){
                bodyBuilder.append('&');
            }
        }

        String body  = bodyBuilder.toString();
        LOGV(TAG, "Posting '" + body + " 'to " + url);
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setChunkedStreamingMode(0);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
            conn.setRequestProperty("Content-Length",Integer.toString(body.length()));

            OutputStream out = conn.getOutputStream();
            out.write(body.getBytes());
            out.close();

            int status = conn.getResponseCode();
            if (status != 200){
                throw new IOException("Post failed with error code "+status);
            }
        }finally{
            if(conn != null ){
                conn.disconnect();
            }
        }
    }
}
